package com.demo.excel;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.demo.eneity.User;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.*;

@Getter
@Component
@Slf4j
public class MultiThreadListener extends AnalysisEventListener<User> {

    private List<User> list = Collections.synchronizedList(new ArrayList<>());
    private final static int CORE_POOL_SIZE = 5;//核心线程数
    private final static int MAX_POOL_SIZE = 10;//最大线程数
    private final static int QUEUE_CAPACITY = 100;//队列大小
    private final static long KEEP_ALIVE_TIME = 1L;//存活时间

    public MultiThreadListener() {

    }

    @Override
    public void invoke(User user, AnalysisContext analysisContext) {
        if (user != null) {
            list.add(user);
        }
    }



    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        log.info("解析完毕，开始插入新数据");
        //创建一个新的线程池
        ExecutorService executorService = new ThreadPoolExecutor(CORE_POOL_SIZE,
                MAX_POOL_SIZE,
                KEEP_ALIVE_TIME,
                TimeUnit.MINUTES,
                new ArrayBlockingQueue<>(QUEUE_CAPACITY),
                new ThreadPoolExecutor.CallerRunsPolicy());
        //设置每个线程处理数据的数量
        int singleTreadDealCount = 1000;
        //要提交到线程池的线程数量
        int threadSize = (list.size() / singleTreadDealCount) + 1;
        //开始位置
        int startIndex = 0;
        //结束位置
        int endIndex = 0;
        //初始化闭锁,数量为线程数量
        CountDownLatch countDownLatch = new CountDownLatch(threadSize);
        for (int i = 0; i < threadSize; i++) {
            //最后一个的结束位置是数组的大小
            if ((i + 1) == threadSize) {
                startIndex = i * singleTreadDealCount;
                endIndex = list.size();
            } else {
                startIndex = i * singleTreadDealCount;
                endIndex = (i + 1) * singleTreadDealCount;
            }
            //创建自定义线程任务类,执行run方法
            UserThread thread = new UserThread(startIndex,endIndex,list,countDownLatch);
            executorService.execute(thread);
        }
        try {
            //当前线程开始等待
            countDownLatch.await();
        }catch (InterruptedException e){
            e.printStackTrace();
        }
        //通过countDownLatch控制所有线程都执行完,再关闭线程池
        executorService.shutdown();
        list.clear();
    }
}
